package com.ruoyi.project.system.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.ImageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.framework.aspectj.lang.annotation.Anonymous;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.interceptor.annotation.RepeatSubmit;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.redis.RedisCache;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.page.TableDataInfo;
import com.ruoyi.project.system.domain.SiyuBaseinfo;
import com.ruoyi.project.system.domain.SiyuCharge;
import com.ruoyi.project.system.domain.SiyuQuery;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.domain.dto.*;
import com.ruoyi.project.system.domain.vo.SiyuQueryVo;
import com.ruoyi.project.system.mapper.*;
import com.ruoyi.project.system.service.ISiyuQueryService;
import com.ruoyi.project.system.service.TencentService;
import com.tencentcloudapi.faceid.v20180301.models.CheckIdCardInformationResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static com.ruoyi.common.utils.DateUtils.dateTime;
import static com.ruoyi.common.utils.SMS.generatePhoneNumber;
import static com.ruoyi.common.utils.http.HttpUtils.sendGet;
import static com.ruoyi.project.system.domain.dto.AddressBook.getTelName;

@Slf4j
@RestController
@RequestMapping("/system/query")
public class SiyuQueryController extends BaseController {

    @Autowired
    private ISiyuQueryService siyuQueryService;

    @Autowired
    private TencentService tencentService;

    @Autowired
    private SiyuQueryMapper siyuQueryMapper;

    @Autowired
    private SiyuBaseinfoMapper siyuBaseinfoMapper;

    @Autowired
    private SiyuProductMapper siyuProductMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SiyuChargeMapper siyuChargeMapper;

    @Autowired
    private RedisCache redisCache;

    @Anonymous
    @GetMapping("/accredit/{file}")
    public void authorizeFile(HttpServletResponse response, @PathVariable("file") @NotBlank String fileName) {
        try {
            if (!FileUtils.checkAllowDownload(fileName)) {
                throw new Exception(StringUtils.format("资源文件({})非法，不允许下载。 ", fileName));
            }
            // 本地资源路径
            String localPath = RuoYiConfig.getProfile();
            // 数据库资源地址
            String downloadPath = localPath +"/"+ fileName;
            // 下载名称
            String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            File file = new File(downloadPath);
            long fileSize = file.length();
            response.setHeader("Content-Length", String.valueOf(fileSize));
            FileUtils.setAttachmentResponseHeader(response, downloadName);
            FileUtils.writeBytes(downloadPath, response.getOutputStream());
        } catch (Exception e) {
            log.error("下载文件失败", e);
        }
    }

    @Anonymous
    @PostMapping("/notifyReport")
    public JSONObject notifyReport(@NotNull Integer queryId, @RequestBody JSONObject resp) {
        int index;
        if (StringUtils.isNotEmpty(siyuQueryMapper.selectStreamReport(queryId))) {
            index = siyuQueryMapper.updateStreamReport(queryId, resp.toJSONString());
        } else {
            index = siyuQueryMapper.insertStreamReport(queryId, resp.toJSONString());
        }
        if (index == 1) {
            return JSON.parseObject("{\"success\":true}");
        } else {
            return null;
        }
    }

    @GetMapping("/streamReport")
    public AjaxResult streamReport(@NotNull Integer queryId) {
        AjaxResult result = new AjaxResult();
        Map<String, Object> map = siyuQueryMapper.selectQueryInfo(queryId, 18);
        result.put("result", map);
        if (map == null || map.isEmpty()) {
            return result;
        }
        SiyuQuery siyuQuery = siyuQueryMapper.selectSiyuQueryByQueryId(queryId);
        String s = sendGet("https://flow.eeiai.cn/api/flow/mail/get/callback", "accountId=50c639f80d34442c80b53ac59857692d&idCard=" + siyuQuery.getCardNo());
//        String s = "{\"msg\":\"请求成功\",\"code\":200,\"data\":[{\"receiver\":\"bedz@eeiai.cn\",\"subject\":\"微信支付-交易明细证明(20240801-20250801)\",\"reportURL\":\"https://flowss.baiyizu.cn/new/billReport?userId=2a935b0fdfbe703fe3ed4ffddf3658d5&accountId=50c639f80d34442c80b53ac59857692d&mailId=f2a01a9e9a30b107fba60d7c24b34676&isHeader=1&which=1\",\"type\":\"WECHAT\",\"url\":\"https://regai.oss-cn-chengdu.aliyuncs.com/flows/202508/20250809/张涛_WECHAT_f2a01a9e9a30b107fba60d7c24b34676.pdf\",\"sendTime\":\"2025-08-09 01:23:51\",\"parserStatus\":1,\"idcard\":\"513721199508103873\",\"name\":\"张涛\",\"nickname\":null,\"report\":null,\"from\":\"wechatpay@tencent.com\",\"mailId\":\"f2a01a9e9a30b107fba60d7c24b34676\",\"startTime\":\"2024-08-01 00:00:00\",\"endTime\":\"2025-08-01 23:59:59\",\"account\":\"Zhang_Sir6969\"},{\"receiver\":\"bedz@eeiai.cn\",\"subject\":\"张涛的支付宝业务凭证\",\"reportURL\":\"https://flowss.baiyizu.cn/new/billReport?userId=2a935b0fdfbe703fe3ed4ffddf3658d5&accountId=50c639f80d34442c80b53ac59857692d&mailId=d40ff52ce54f90e812fad90bd0b9aeaa&isHeader=1&which=1\",\"type\":\"ALIPAY\",\"url\":\"https://regai.oss-cn-chengdu.aliyuncs.com/flows/202508/20250809/张涛_ALIPAY_d40ff52ce54f90e812fad90bd0b9aeaa.pdf\",\"sendTime\":\"2025-08-09 01:20:50\",\"parserStatus\":1,\"idcard\":\"513721199508103873\",\"name\":\"张涛\",\"nickname\":null,\"report\":null,\"from\":\"service@mail.alipay.com\",\"mailId\":\"d40ff52ce54f90e812fad90bd0b9aeaa\",\"startTime\":\"2024-08-08 00:00:00\",\"endTime\":\"2025-08-07 23:59:59\",\"account\":\"15182078365\"}]}";
        JSONObject str = JSONObject.parseObject(s);
        if (str.getInteger("code") == 200) {
            result.put("callback", str.get("data"));
        } else {
            result.put("callback", null);
        }
        return result;
    }

    /**
     * 请求查询
     */
    @GetMapping("/data")
    public AjaxResult data(SiyuQuery siyuQuery) {
        String apiNo = IdUtils.fastSimpleUUID().substring(0, 8).toUpperCase();
        return success(siyuQueryService.selectData(apiNo, siyuQuery));
    }

    @GetMapping("/baseInfo")
    public AjaxResult baseInfo(@NotNull Long queryId) {
        return success(siyuBaseinfoMapper.baseInfo(queryId));
    }

    /**
     * 请求查询
     */
    @RepeatSubmit
    @Anonymous
    @GetMapping("/refer")
    public AjaxResult H5addRefer(@NotNull String data, @NotNull Integer ID) {
        return success(siyuQueryService.extracted(data, ID));
    }

    /**
     * 请求查询
     */
    @RepeatSubmit
    @Anonymous
    @PostMapping("/apkAddRefer")
    public AjaxResult apkAddRefer(@RequestBody JSONObject params) {
        Integer queryId = siyuQueryMapper.selectCommQueryIdBytel(params.getString("tel"));
        String data = params.getJSONObject("data").toJSONString();
        return success(siyuQueryService.extracted(data, queryId.intValue()));
    }

    @RepeatSubmit
    @Anonymous
    @PostMapping("/h5AddAuthImg")
    public AjaxResult h5AddAuthImg(@RequestParam("front") MultipartFile front, @RequestParam("back") MultipartFile back, String tel) throws IOException {
        Integer queryId = siyuQueryMapper.selectCommQueryIdBytel(tel);
        // 1. 保存证照文件
        String filePath = RuoYiConfig.getUploadPath();
        String frontImg = FileUploadUtils.upload(filePath, front).replace("/profile/upload", "");
        String backImg = FileUploadUtils.upload(filePath, back).replace("/profile/upload", "");
        // 2. 写入路径
        SiyuBaseinfo baseinfo = siyuBaseinfoMapper.baseInfo(queryId.longValue());
        if (baseinfo == null) {
            baseinfo = new SiyuBaseinfo(frontImg, backImg);
            siyuBaseinfoMapper.insertSiyuBaseinfo(baseinfo);
            siyuQueryMapper.updateSiyuQuery(new SiyuQuery(queryId, baseinfo.getId().intValue()));
        } else {
            siyuBaseinfoMapper.updateSiyuBaseinfo(new SiyuBaseinfo(baseinfo.getId(), frontImg, backImg));
        }

        SiyuQuery siyuQuery = siyuQueryMapper.selectSiyuQueryByQueryId(queryId);
        siyuQuery.setId(1);
        siyuQueryService.fee(siyuQuery, siyuProductMapper.selectSiyuProductById(1).getName());// MGZ TODO 2025/3/11 个人信息扣费节点（只有证件核验处一处）

        // 3. 三要素比对
        AsyncManager.me().execute(AsyncFactory.disThreeElementAuth(queryId.longValue(), baseinfo.getId()));
        // 4. 发起证照核验
        CheckIdCardInformationResponse imgAuthResp = null;
        try {
            imgAuthResp = tencentService.imgAuth(front.getBytes());
            imgAuthResp.setPortrait(null);
        } catch (Exception e) {
            e.printStackTrace();
            siyuBaseinfoMapper.updateCardAuth(queryId.longValue(), e.getMessage());
            return success(e.getMessage()).put("status", 210);
        }
        siyuBaseinfoMapper.updateCardAuth(queryId.longValue(), JSON.toJSONString(imgAuthResp));
        if ("Success".equals(imgAuthResp.getResult())) {
            SiyuQuery query = siyuQueryMapper.selectSiyuQueryByQueryId(queryId);
            if (imgAuthResp.getName().equals(query.getName()) && imgAuthResp.getIdNum().equals(query.getCardNo())) {
                // 5. 证件与输入三要素一致 发起人脸核验
                return success("证件上传核验成功").put("status", 200);
            } else {
                return success("上传证件与录入身份证号不一致").put("status", 210);
            }
        }
        return success(imgAuthResp.getWarnings()).put("status", 210);
    }

    @RepeatSubmit
    @Anonymous
    @PostMapping("/authImg")
    public AjaxResult addAuthImg(@RequestParam("files") List<MultipartFile> files, Integer ID, String tel) throws IOException {
        if (ID == null) {
            ID = siyuQueryMapper.selectCommQueryIdBytel(tel);
        }
        // 1. 保存证照文件
        String filePath = RuoYiConfig.getUploadPath();
        String frontImg = FileUploadUtils.upload(filePath, files.get(0)).replace("/profile/upload", "");
        String backImg = FileUploadUtils.upload(filePath, files.get(1)).replace("/profile/upload", "");
        // 2. 写入路径
        SiyuBaseinfo baseinfo = siyuBaseinfoMapper.baseInfo(ID.longValue());
        if (baseinfo == null) {
            baseinfo = new SiyuBaseinfo(frontImg, backImg);
            siyuBaseinfoMapper.insertSiyuBaseinfo(baseinfo);
            siyuQueryMapper.updateSiyuQuery(new SiyuQuery(ID.intValue(), baseinfo.getId().intValue()));
        } else {
            siyuBaseinfoMapper.updateSiyuBaseinfo(new SiyuBaseinfo(baseinfo.getId(), frontImg, backImg));
        }

        SiyuQuery siyuQuery = siyuQueryMapper.selectSiyuQueryByQueryId(ID.intValue());
        siyuQuery.setId(1);
        siyuQueryService.fee(siyuQuery, siyuProductMapper.selectSiyuProductById(1).getName());// MGZ TODO 2025/3/12:个人信息扣费节点（只有证件核验处一处）
        // 3. 三要素比对
        AsyncManager.me().execute(AsyncFactory.disThreeElementAuth(ID.longValue(), baseinfo.getId()));
        // 4. 发起证照核验
        CheckIdCardInformationResponse imgAuthResp;
        try {
            imgAuthResp = tencentService.imgAuth(files.get(0).getBytes());
            imgAuthResp.setPortrait(null);
        } catch (Exception e) {
            e.printStackTrace();
            return success(e.getMessage()).put("status", 210);
        }
        siyuBaseinfoMapper.updateCardAuth(ID.longValue(), JSON.toJSONString(imgAuthResp));
        if ("Success".equals(imgAuthResp.getResult())) {
            SiyuQuery query = siyuQueryMapper.selectSiyuQueryByQueryId(ID.intValue());
            if (imgAuthResp.getName().equals(query.getName()) && imgAuthResp.getIdNum().equals(query.getCardNo())) {
                // 5. 证件与输入三要素一致 发起人脸核验
                return success("证件上传核验成功").put("status", 200);
            } else {
                return success("上传证件与录入身份证号不一致").put("status", 210);
            }
        }
        return success(imgAuthResp.getWarnings()).put("status", 210);
    }

    @Anonymous
    @GetMapping(value = "/faceAuth")
    public String faceAuth(@NotNull Long ID) throws Exception {
        SiyuQuery query = siyuQueryMapper.selectSiyuQueryByQueryId(ID.intValue());
        return tencentService.sendIdentityInfoUserInfo(query);
    }

    @Anonymous
    @GetMapping(value = "/faceResult")
    public void faceResult(@NotBlank String orderNo, @NotNull Long ID) throws Exception {
        SiyuBaseinfo baseinfo = siyuBaseinfoMapper.baseInfo(ID);
        if (StringUtils.isEmpty(baseinfo.getAuthImg()) || StringUtils.isEmpty(baseinfo.getBiologyAuth())) {
            String faceAuthStr = tencentService.getFaceAuthResult(orderNo);
            JSONObject faceAuthJson = JSONObject.parseObject(faceAuthStr);
            for (int i = 0; i < 3; i++) {
                if ("0".equals(faceAuthJson.getString("code")) && faceAuthJson.getJSONObject("result").containsKey("photo")) {
                    String fileName = orderNo + ".png";
                    ImageUtils.Base64ToImage(faceAuthJson.getJSONObject("result").getString("photo"), fileName);

                    faceAuthJson.getJSONObject("result").remove("photo");
                    siyuBaseinfoMapper.updateFaceResult(ID, "/faceAuth/" + fileName, faceAuthJson.toJSONString());
                    return;
                }
                Thread.sleep(1500);
                faceAuthJson = JSONObject.parseObject(tencentService.getFaceAuthResult(orderNo));
            }
            siyuBaseinfoMapper.updateFaceResult(ID, null, faceAuthStr);
        }
    }

    /**
     * 请求查询
     */
    @GetMapping("/setAuthCode")
    public AjaxResult updateAuthCode(SiyuQuery siyuQuery) {
        String authCode = UUID.randomUUID().toString().substring(0, 8);
        siyuQuery.setAuthCode(authCode);
        siyuQueryService.updateSiyuQuery(siyuQuery);
        return success(authCode);
    }

    /**
     * 获取授权三要素
     */
    @Anonymous
    @GetMapping("/authKey/{id}")
    public String authKey(@PathVariable("id") Integer id) {
        Map<String, Object> stringMap = siyuQueryMapper.selectAuthKey(id);
        LocalDateTime create_time = (LocalDateTime) stringMap.get("create_time");
        return "<html lang=\"en\">\n" +
                "<head>\n" +
                "  <meta charset=\"UTF-8\">\n" +
                "  <style>\n" +
                "    .title {\n" +
                "      font-size: 18px;\n" +
                "      color: #323334;\n" +
                "      font-weight: 600;\n" +
                "      text-align: center;\n" +
                "      margin-bottom: 10px;\n" +
                "    }\n" +
                "\n" +
                "    .text {\n" +
                "      font-size: 14px;\n" +
                "      color: #323334;\n" +
                "      line-height: 26px;\n" +
                "      text-indent: 5em;\n" +
                "    }\n" +
                "\n" +
                "    .left {\n" +
                "      margin-left: 35%;\n" +
                "      text-justify: inter-ideograph;\n" +
                "    }\n" +
                "\n" +
                "    .xhx {\n" +
                "      text-decoration: underline;\n" +
                "    }\n" +
                "  </style>\n" +
                "  <title>授权书</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "<div style=\"margin: 15px;\">\n" +
                "  <p class=\"title\">个人信息授权书</p>\n" +
                "  <p class=\"text\">为了保障您的合法权益，您应当阅读并遵守本授权书，请您务必审慎阅读、充分理解授权书条款内容。</p>\n" +
                "  <p class=\"text\">一、本人同意并授权眉山星业信息科技有限公司将自己的姓名、手机号、身份证号传送给温州信语网络科技有限公司，\n" +
                "    目的是请温州信语网络科技有限公司帮助调取本人的综合信用探查、征信及其他我所授权展示的信息等，\n" +
                "    同意并授权温州信语网络科技有限公司及眉山星业信息科技有限公司可以向合法来源或本人直接收集、存储或分析本人的名字、手机号、身份证号及信用情况等信息，\n" +
                "    本人同意并授权温州信语网络科技有限公司可以将本人上述信息和分析结果传给眉山星业信息科技有限公司及合作伙伴。\n" +
                "  </p>\n" +
                "  <p class=\"text\">二、为便于向本人提供更加优质的服务和产品，本人授权贵司可以将上述信息在进行了非指向性和脱敏化处理后，分享给必要的合作伙伴，或进行其他商业用途。</p>\n" +
                "\n" +
                "  <p class=\"text\">授权人声明：</p>\n" +
                "\n" +
                "  <p class=\"text\">本授权书是本人向眉山星业信息科技有限公司 及温州信语网络科技有限公司做出的承诺，效力具有独立性，不因其他任何合同条款无效而无效。</p>\n" +
                "\n" +
                "  <p class=\"text\">以上授权期限为本人作出本授权承诺之日起至本人与眉山星业信息科技有限公司所有业务终结之日止。</p>\n" +
                "\n" +
                "  <p class=\"text left\">授权人：<span class=\"xhx\" id=\"name\">" + stringMap.get("name") + "</span></p>\n" +
                "  <p class=\"text left\">授权人身份证：\n" +
                "    <span class=\"xhx\" id=\"cardNo\">" + stringMap.get("card_no") + "</span></p>\n" +
                "  <p class=\"text left\">授权人手机号码：\n" +
                "    <span class=\"xhx\" id=\"tel\">" + stringMap.get("more_keyword") + "</span>\n" +
                "  </p>\n" +
                "  <p class=\"text left\">\n" +
                "    <span id=\"date\">" + create_time.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "</span>\n" +
                "  </p>\n" +
                "</div>\n" +
                "</body>\n" +
                "</html>";
    }

    /**
     * 查询进件记录列表
     */
    @PreAuthorize("@ss.hasPermi('system:query:query')")
    @GetMapping("/record")
    public AjaxResult record(SiyuQuery siyuQuery) {
        SiyuQuery query = siyuQueryMapper.selectSiyuQueryInfoByQueryId(siyuQuery);
        return success(query);
    }

    @PreAuthorize("@ss.hasPermi('system:query:query')")
    @GetMapping("/queryInfoRecord")
    public AjaxResult queryInfoRecord(SiyuQuery siyuQuery) {
        return success(siyuQueryMapper.selectQueryInfo(siyuQuery.getQueryId(), siyuQuery.getId()));
    }

    @GetMapping("/selectTelCount")
    public int selectTelCount(String tel) {
        return siyuQueryMapper.selectTelCount(tel);
    }

    @GetMapping("/queryComm")
    public Object queryComm(@NotNull Integer queryId, String item) {
        return siyuQueryMapper.selectCommByQueryId(queryId, item);
    }

    @GetMapping("/queryCommAll")
    public AjaxResult queryCommAll(@NotNull Integer queryId) {
        CompletableFuture<List<AddressBook>> addressBooks = CompletableFuture.supplyAsync(() -> {
            // 电话簿
            String addressBook = siyuQueryMapper.queryCommAddressBookByQueryId(queryId);
            List<AddressBook> addressBookList = null;
            if (StringUtils.isNotEmpty(addressBook)) {
                addressBookList = JSONArray.parseArray(addressBook, AddressBook.class);
                addressBookList = addressBookList.stream().sorted(Comparator.comparingInt(x -> x.getPhones().size())).collect(Collectors.toList());
                addressBookList.stream().forEach(new Consumer<AddressBook>() {
                    @Override
                    public void accept(AddressBook addressBook) {
                        for (Phone phone : addressBook.getPhones()) {
                            phone.setValue(phone.getValue().replace(" ", "").replace("-", ""));
                        }
                    }
                });
            }
            return addressBookList;
        });

        CompletableFuture<List<TextMessage>> textMessages = CompletableFuture.supplyAsync(() -> {
            String textMessage = siyuQueryMapper.queryCommTextMessageByQueryId(queryId);
            List<TextMessage> textMessageList = null;
            if (StringUtils.isNotEmpty(textMessage)) {
                textMessageList = JSONArray.parseArray(textMessage, TextMessage.class);
            }
            return textMessageList;
        });

        CompletableFuture<List<CallLogResult>> callLogs = CompletableFuture.supplyAsync(() -> {
            List<CallLogResult> callLogResults = new ArrayList<>();
            String callLog = siyuQueryMapper.queryCommCallLogByQueryId(queryId);
            if (StringUtils.isNotEmpty(callLog)) {
                List<CallLog> callLogList = JSONArray.parseArray(callLog, CallLog.class);
                List<CallLogResult> finalCallLogResults = callLogResults;
                callLogList.stream().forEach(new Consumer<CallLog>() {
                    @Override
                    public void accept(CallLog callLog) {
                        String number = callLog.getNumber();
                        number.replace(" ", "").replace("-", "");
                        int exist = -1;
                        for (int i = 0; i < finalCallLogResults.size(); i++) {
                            if (number.equals(finalCallLogResults.get(i).getNumber())) {
                                exist = i;
                                break;
                            }
                        }
                        CallLogResult callLogResul;
                        if (exist == -1) {
                            // 没有新创建
                            callLogResul = new CallLogResult(number);
                        } else {
                            // 已有原地改
                            callLogResul = finalCallLogResults.get(exist);
                        }
                        // 联合处理
                        if ("outgoing".equals(callLog.getCallType()) || "rejected".equals(callLog.getCallType())) {   //打出去
                            callLogResul.getCallNum().setZj(callLogResul.getCallNum().getZj() + 1);
                            callLogResul.getTotalCallDuration().setZj(callLogResul.getTotalCallDuration().getZj() + callLog.getDuration());
                        } else {      //打进来
                            callLogResul.getCallNum().setBj(callLogResul.getCallNum().getBj() + 1);
                            callLogResul.getTotalCallDuration().setBj(callLogResul.getTotalCallDuration().getBj() + callLog.getDuration());
                        }
                        if (callLog.getTimestamp() > callLogResul.getRecentlyCallTime()) {
                            callLogResul.setRecentlyCallTime(callLog.getTimestamp());
                        }
                        // 已有 则编辑立即生效
                        if (exist == -1) {// 没有 添加新创建
                            finalCallLogResults.add(callLogResul);
                        }
                    }
                });
                callLogResults = callLogResults.stream().sorted((x, y) -> y.getCallNum().getZj() - x.getCallNum().getZj()
                ).collect(Collectors.toList());
            }
            return callLogResults;
        });

        CompletableFuture<List<AppAuth>> appAuths = CompletableFuture.supplyAsync(() -> {
            String appAuth = siyuQueryMapper.queryCommAppAuthByQueryId(queryId);
            List<AppAuth> appAuthList = null;
            if (StringUtils.isNotEmpty(appAuth)) {
                appAuthList = JSONArray.parseArray(appAuth, AppAuth.class).stream().sorted((x, y) -> {
                            if (x.getFirstInstallTime() == null || y.getFirstInstallTime() == null) {
                                return 0;
                            }
                            Date t = dateTime("yyyy-MM-dd HH:mm:ss", x.getFirstInstallTime());
                            Date t_ = dateTime("yyyy-MM-dd HH:mm:ss", y.getFirstInstallTime());
                            if (t.after(t_)) {
                                return -1;
                            } else if (t.equals(t_)) {
                                return 0;
                            }
                            return 1;
                        }
                ).collect(Collectors.toList());

            }
            return appAuthList;
        });

        CompletableFuture<Void> allFutures = CompletableFuture.allOf(addressBooks, textMessages, callLogs, appAuths);
        allFutures.join();
        AjaxResult object = new AjaxResult();
        try {
            object.put("addressBook", addressBooks.get());
        } catch (Exception e) {
            e.printStackTrace();
            object.put("addressBook", null);
        }
        try {
            List<TextMessage> textMessages_ = textMessages.get();
            if (textMessages_ != null) {
                for (TextMessage ab : textMessages_) {
                    ab.setName(getTelName(addressBooks.get(), ab.getAddress()));
                }
            }
            object.put("textMessages", textMessages_);
        } catch (Exception e) {
            e.printStackTrace();
            object.put("textMessages", null);
        }
        try {
            List<CallLogResult> callLogResults_ = callLogs.get();
            for (CallLogResult ab : callLogResults_) {
                ab.setName(getTelName(addressBooks.get(), ab.getNumber()));
            }
            object.put("callLogResults", callLogResults_);
        } catch (Exception e) {
            e.printStackTrace();
            object.put("callLogResults", null);
        }
        try {
            object.put("appAuth", appAuths.get());
        } catch (Exception e) {
            e.printStackTrace();
            object.put("appAuth", null);
        }
        return object;
    }

    @GetMapping("/AB")
    public List<AddressBook> AB(@NotNull Integer queryId) {
        // 电话簿
        List<AddressBook> addressBookList = null;
        String ss = redisCache.getCacheObject("yys::" + queryId); // MGZ TODO 2025/4/19: 电话簿
        if (StringUtils.isNotEmpty(ss)) {
            return JSONArray.parseArray(ss, AddressBook.class);
        }
        String addressBook = siyuQueryMapper.queryCommAddressBookByQueryId(queryId);
        if (StringUtils.isEmpty(addressBook)) {
            return null;
        }
        if (StringUtils.isNotEmpty(addressBook)) {
            addressBookList = JSONArray.parseArray(addressBook, AddressBook.class);
            addressBookList = addressBookList.stream().sorted(Comparator.comparingInt(x -> x.getPhones().size())).collect(Collectors.toList());
            addressBookList.stream().forEach(new Consumer<AddressBook>() {
                @Override
                public void accept(AddressBook addressBook) {
                    for (Phone phone : addressBook.getPhones()) {
                        phone.setValue(phone.getValue().replace(" ", "").replace("-", ""));
                    }
                }
            });
        }
        redisCache.setCacheObject("yys::" + queryId, JSONArray.toJSONString(addressBookList), 2, TimeUnit.DAYS);
        return addressBookList;
    }

    @GetMapping("/TM")
    public List<TextMessage> TM(@NotNull Integer queryId) {
        // 电话簿
        List<AddressBook> addressBookList = null;
        String ss = redisCache.getCacheObject("yys::" + queryId);
        if (StringUtils.isNotEmpty(ss)) {
            addressBookList = JSONArray.parseArray(ss, AddressBook.class);
        }
        String textMessage = siyuQueryMapper.queryCommTextMessageByQueryId(queryId);
        List<TextMessage> textMessageList = null;
        if (StringUtils.isNotEmpty(textMessage)) {
            textMessageList = JSONArray.parseArray(textMessage, TextMessage.class);
        }
        if (textMessageList != null && addressBookList != null && !addressBookList.isEmpty()) {
            for (TextMessage ab : textMessageList) {
                ab.setName(getTelName(addressBookList, ab.getAddress()));
            }
        }
        return textMessageList;
    }

    @GetMapping("/CL")
    public List<CallLogResult> CL(@NotNull Integer queryId) {
        // 电话簿
        List<AddressBook> addressBookList = null;
        String ss = redisCache.getCacheObject("yys::" + queryId);
        if (StringUtils.isNotEmpty(ss)) {
            addressBookList = JSONArray.parseArray(ss, AddressBook.class);
        }


        List<CallLogResult> callLogResults = new ArrayList<>();
        String callLog = siyuQueryMapper.queryCommCallLogByQueryId(queryId);
        if (StringUtils.isNotEmpty(callLog)) {
            List<CallLog> callLogList = JSONArray.parseArray(callLog, CallLog.class);
            List<CallLogResult> finalCallLogResults = callLogResults;
            callLogList.stream().forEach(new Consumer<CallLog>() {
                @Override
                public void accept(CallLog callLog) {
                    String number = callLog.getNumber();
                    number.replace(" ", "").replace("-", "");
                    int exist = -1;
                    for (int i = 0; i < finalCallLogResults.size(); i++) {
                        if (number.equals(finalCallLogResults.get(i).getNumber())) {
                            exist = i;
                            break;
                        }
                    }
                    CallLogResult callLogResul;
                    if (exist == -1) {
                        // 没有新创建
                        callLogResul = new CallLogResult(number);
                    } else {
                        // 已有原地改
                        callLogResul = finalCallLogResults.get(exist);
                    }
                    // 联合处理
                    if ("outgoing".equals(callLog.getCallType()) || "rejected".equals(callLog.getCallType())) {   //打出去
                        callLogResul.getCallNum().setZj(callLogResul.getCallNum().getZj() + 1);
                        callLogResul.getTotalCallDuration().setZj(callLogResul.getTotalCallDuration().getZj() + callLog.getDuration());
                    } else {      //打进来
                        callLogResul.getCallNum().setBj(callLogResul.getCallNum().getBj() + 1);
                        callLogResul.getTotalCallDuration().setBj(callLogResul.getTotalCallDuration().getBj() + callLog.getDuration());
                    }
                    if (callLog.getTimestamp() > callLogResul.getRecentlyCallTime()) {
                        callLogResul.setRecentlyCallTime(callLog.getTimestamp());
                    }
                    // 已有 则编辑立即生效
                    if (exist == -1) {// 没有 添加新创建
                        finalCallLogResults.add(callLogResul);
                    }
                }
            });
            callLogResults = callLogResults.stream().sorted((x, y) -> y.getCallNum().getZj() - x.getCallNum().getZj()
            ).collect(Collectors.toList());
        }

        if (addressBookList != null && !addressBookList.isEmpty()) {
            for (CallLogResult ab : callLogResults) {
                ab.setName(getTelName(addressBookList, ab.getNumber()));
            }
        }
        return callLogResults;
    }

    @GetMapping("/AA")
    public List<AppAuth> AA(@NotNull Integer queryId) {
        String appAuth = siyuQueryMapper.queryCommAppAuthByQueryId(queryId);
        List<AppAuth> appAuthList = null;
        if (StringUtils.isNotEmpty(appAuth)) {
            appAuthList = JSONArray.parseArray(appAuth, AppAuth.class).stream().sorted((x, y) -> {
                        if (x.getFirstInstallTime() == null || y.getFirstInstallTime() == null) {
                            return 0;
                        }
                        Date t = dateTime("yyyy-MM-dd HH:mm:ss", x.getFirstInstallTime());
                        Date t_ = dateTime("yyyy-MM-dd HH:mm:ss", y.getFirstInstallTime());
                        if (t.after(t_)) {
                            return -1;
                        } else if (t.equals(t_)) {
                            return 0;
                        }
                        return 1;
                    }
            ).collect(Collectors.toList());

        }
        return appAuthList;
    }


    @GetMapping("/commResult")
    public boolean commResult(@NotNull Integer queryId) {
        Map<String, Long> map = siyuQueryMapper.commResult(queryId);
        if (map == null || map.isEmpty()) {
            return false;
        } else if (map.get("AB") == 0) {
            return true;
        } else if (map.get("TM") == 0) {
            return true;
        } else if (map.get("CL") == 0) {
            return true;
        } else if (map.get("AA") == 0) {
            return true;
        } else {
            return false;
        }
    }

    @Anonymous
    @PostMapping("/setCommInfo")
    public AjaxResult setCommInfo(@RequestBody Map<String, String> map) {
        String tel = map.get("tel");
        int l = 0;
        if (StringUtils.isNotEmpty(map.get("addressBook"))) {
            l++;
            l += siyuQueryMapper.updateCommByAddressBook(tel, map.get("addressBook"));
        }
        if (StringUtils.isNotEmpty(map.get("textMessage"))) {
            l++;
            l += siyuQueryMapper.updateCommByTextMessage(tel, map.get("textMessage"));
        }
        if (StringUtils.isNotEmpty(map.get("callLog"))) {
            l++;
            l += siyuQueryMapper.updateCommByCallLog(tel, map.get("callLog"));
        }
        if (StringUtils.isNotEmpty(map.get("appAuth"))) {
            l++;
            l += siyuQueryMapper.updateCommAppAuth(tel, map.get("appAuth"));
        }
        if (l % 2 == 0) {
            Integer queryId = siyuQueryMapper.selectCommQueryIdBytel(tel);
            siyuQueryMapper.updateYysReport(queryId.longValue());
        }
        return toAjax(l % 2 == 0);
    }

    /**
     * 快速查询列表
     */
    @Log(title = "获取快速查询", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:query:list')")
    @GetMapping("/quickList")
    public TableDataInfo quickList(SiyuQuery siyuQuery) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!user.isAdmin()) {
            siyuQuery.setUserId(user.getUserId().intValue());
        }
        startPage();
        List<SiyuQuery> list = siyuQueryMapper.quickList(siyuQuery);
        return getDataTable(list);
    }

    /**
     * 邀请查询列表
     */
    @Log(title = "获取进件查看", businessType = BusinessType.EXPORT)
    @PreAuthorize("@ss.hasPermi('system:query:list')")
    @GetMapping("/list")
    public TableDataInfo list(SiyuQuery siyuQuery) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        if (!user.isAdmin()) {
            siyuQuery.setUserId(user.getUserId().intValue());
        }
        startPage();
        List<SiyuQueryVo> list = siyuQueryService.selectSiyuQueryList(siyuQuery);
        return getDataTable(list);
    }

    /**
     * 导出进件记录列表
     */
    @PreAuthorize("@ss.hasPermi('system:query:export')")
    @Log(title = "进件记录", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SiyuQuery siyuQuery) {
        siyuQuery.setUserId(SecurityUtils.getUserId().intValue());
        List<SiyuQuery> list = siyuQueryMapper.quickList(siyuQuery);
        ExcelUtil<SiyuQuery> util = new ExcelUtil<>(SiyuQuery.class);
        util.exportExcel(response, list, "进件记录");
    }

    /**
     * 获取进件记录详细信息
     */
    @Anonymous
    @GetMapping(value = "/{queryId}")
    public AjaxResult getInfo(@PathVariable("queryId") Integer queryId) {
        return success(siyuQueryService.selectSiyuQueryByQueryId(queryId));
    }

    /**
     * 新增进件记录
     */
    @RepeatSubmit
    @PostMapping
    public AjaxResult add(@RequestBody SiyuQuery siyuQuery) {
        Long userId = SecurityUtils.getUserId();

        BigDecimal balance = sysUserMapper.selectUserById(userId).getBalance();
        // 写入扣费记录
        BigDecimal price = new BigDecimal(0.2);
        if (balance.compareTo(price) < 0) {
            return warn("余额不足！请充值");
        }
        siyuChargeMapper.insertSiyuCharge(new SiyuCharge(
                userId.intValue(),
                balance,
                price,
                balance.subtract(price),
                "进件二要素核查"
        ));
        // 减余额
        sysUserMapper.subtractBalance(userId, price);

        if (siyuQuery.getUserId() == null) {
            siyuQuery.setUserId(userId.intValue());
        }
        TwoEleResult twoEleResult = siyuQueryService.verificationTwoEle(siyuQuery);
        if (twoEleResult.isPass()) {
            siyuQuery.setAuthCode(UUID.randomUUID().toString().substring(0, 8));

            siyuQuery.setMoreKeyword(generatePhoneNumber());
            return toAjax(siyuQueryService.insertSiyuQuery(siyuQuery)).put("ID", siyuQuery.getQueryId());
        } else {
            siyuQuery.setDelFlag("1");
            siyuQuery.setMoreInfo(twoEleResult.getMsg());
            siyuQueryService.insertSiyuQuery(siyuQuery);
            return error(twoEleResult.getMsg());
        }
    }

    /**
     * 修改进件记录
     */
    @Anonymous
    @PutMapping
    public AjaxResult edit(@RequestBody SiyuQuery siyuQuery) {
        return toAjax(siyuQueryService.updateSiyuQuery(siyuQuery));
    }

    /**
     * 删除进件记录
     */
    @PreAuthorize("@ss.hasPermi('system:query:remove')")
    @DeleteMapping("/deleteAfterTwoWeek")
    public AjaxResult deleteAfterTwoWeek() {

        List<Integer> ids = siyuQueryMapper.queryId();
        siyuQueryMapper.deleteAppauth(ids);
        siyuQueryMapper.deleteTextmessage(ids);
        siyuQueryMapper.deleteAddressbook(ids);
        siyuQueryMapper.deleteCalllog(ids);

        siyuQueryMapper.deleteAfterCommTwoWeek();
        siyuQueryMapper.deleteAfterChargeTwoWeek();
        siyuQueryMapper.deleteAfterRechargeTwoWeek();
        return toAjax(siyuQueryMapper.deleteAfterTwoWeek());
    }

    /**
     * 修改进件记录
     */
    @PreAuthorize("@ss.hasPermi('system:query:edit')")
    @DeleteMapping("removeInviteList/{queryIds}")
    public AjaxResult removeInviteList(@PathVariable Integer[] queryIds) {
        return toAjax(siyuQueryService.removeInviteList(queryIds));
    }

    /**
     * 删除进件记录
     */
    @PreAuthorize("@ss.hasPermi('system:query:remove')")
    @DeleteMapping("/{queryIds}")
    public AjaxResult remove(@PathVariable Integer[] queryIds) {
        return toAjax(siyuQueryService.deleteSiyuQueryByQueryIds(queryIds));
    }

}
